#ifndef HALLDEVICE_H
#define HALLDEVICE_H

#include <QObject>
#include "serialcore.h"
#include <QThread>
#include <QDebug>
#include <QMessageBox>
typedef struct ReadRegisterValue
{
    bool success=false;
    unsigned char value=0;
}ReadRegisterValue;
class HallDevice : public QObject
{
    Q_OBJECT
public:
    explicit HallDevice(QObject *parent = nullptr);         //构造函数。里面初始化线程并创建串口对象、连接信号与槽。
    ~HallDevice();                                          //析构函数。销毁对象时先停止线程。
    QThread mthread;                                        //线程对象。用于创建子线程和UI分离。
    SerialCore *serialCoreObject;                           //串口对象。串口的打开、关闭读写功能
    QByteArray recvBuf;                                     //设备的接收缓冲区
    bool hasRecv=false;                                     //为true表示已收到返回数据，为false表示未收到返回数据。
    void OpenDevice();                                      //在子线程中打开设备
    void CloseDevice();                                     //在子线程中关闭设备
    void SlotInit();                                        //初始化信号与槽 打开 关闭 发送

    void SendData(QByteArray sendData,int recvLength);      //外部调用 在子线程中发送数据
    QByteArray RecvProgrammingDeviceData();                 //外部调用 获取返回的数据 也可内部调用
    uchar CRC8(unsigned char *buf,int length);

    ReadRegisterValue ReadSingleRegister(unsigned char registorAddress);      //读单个寄存器
    bool WriteSingleRegister(uchar adress,uchar value);                       //写单个寄存器
    bool HallChipControl(unsigned char type); //1进入通讯 3上电 5下电                                //控制芯片
    bool SingleRegisterBurn(uchar address,uchar registerValue);               //单个寄存器烧录
    bool AllRegisterBurn();                                                   //已写入数据全部烧写
    bool ChannelSwitch(unsigned char channel);                                //切换通道

    bool SwitchToMeasureVoltageMode();
    void Aotu_LoadParam(float value,QString text);
    void ZeroCalibration(float DifferenceValue);

signals:
    void ToCreateDevice();
    void ToOpenDevice();
    void ToCloseDevice();
    void ToSendData(QByteArray sendData,int recvLength);
    void ToShowMessageBox(QString);
    void ToShowSendRecv(QString);
public slots:
    void Slot_CreateDevice();
    void Slot_OpenDevcie();
    void Slot_CloseDevice();
    void Slot_SendData(QByteArray sendData,int recvLength);

public:
    bool isShouldTest=true;//如果为false则不进行测试，如果为true则要进行测试
    bool isAlreadyTested=false;

    ReadRegisterValue temp;
    unsigned char TADCHi=0;
    unsigned char TADCLow=0;
    ushort TADC=0;

    unsigned char BurnTimes=0;

    uchar GS302_R30=0;                      //写入0x30寄存器的内容 第一次烧写 0xa2 第二次烧写 0xe6
    uchar GS302_VBIAS=0;                    //用于存储VBIAS寄存器的值
    uchar GS302_R31=0;                      //用于存储R31寄存器的值
    uchar GS302_GG0=0;

    uchar WReg_GG0=0;                       //根据1次还是2次烧录决定是寄存器40还是42
    uchar WReg_VBIAS=0;                     //根据1次还是2次烧录决定是寄存器41还是43 GS302_VBIAS的地址
    uchar MTP_Bank=0;                       //粗调存储区
    uchar LUT_Bank=0;                       //细调存储区

    uchar GS302_TC1=0;                      //0x32 存储要写入的TC1 值来源于界面从配置文件读取的值
    uchar GS302_TC2=0;                      //0x33 存储要写入的TC2 值来源于界面从配置文件读取的值

    float GS302_VEXC;           //计算使用

    float Zero_BasicsOutV;                        //霍尔零点基准测量电压
    float Full_BasicsOutV;                        //霍尔满值基准测量电压
    float Calib_FullOutV;
    float Calib_ZeroOutV;                         //霍尔校准测量实际零点电压
    bool IsGetZeroLSB=false;
    float ZeroVChange=0;
    float ZeroLSB_Value=0;
    float ZeroWriteChange=1;
    float Calib_Un;                               //霍尔校准测量实际量程
    float Calib_ZeroError;                        //零点误差，差分模式下这个误差为（测量值-差分零点）
    float Calib_UnError;                          //量程误差
    int16_t    ZeroWrite_Before;                                //零点粗调写入前
    int16_t    ZeroWrite_After;                                 //零点写入后细调值


    float Zero_ExpectInternalRef=2.5;       //获取内部参考期望零点--内部参考。裸霍尔零点。
    float Zero_ExpectActualRef =0;          //获取外部期望零点--外部参考。带外部电路的零点。
    float Full_ExpectVBIAS =4.5;            //获取外部期望满值。
    float Un_ExpectVBIAS = 2;               //获取外部期望量程
    float RealTimeRef_Zero = 2.5;           //霍尔实时参考零点--用于校准参考（初值在获取外部期望零点获取）
    float RealTimeRef_Un   = 2;             //霍尔实时参考量程--用于校准参考（初值在期望量程获取）

    //***************系数*****************************//
    float       G1_Gain = 1;                //一阶增益
    float       G2_Gain = 1.182;            //二阶增益
    float       Go_Gain = 2.4;              //三阶增益
    float       GainDAC;                                //增益系数
    float       ZeroDAC;                                //零点系数
    //**************
    float       Zero_InternalInV;                       //霍尔内部电压
    float       Full_InternalInV;                       //霍尔内部电压
    float       Un_InternalInV = 0;                     //霍尔内部量程，忽略放大倍数
    //
    float      GS302_ZeroDAC;                           //这个数乘以16383即位寄存器的值
    float      GS302_GainDAC;                           //这个数乘以16383即为灵敏度细调增益

    uint8_t    GS302_K0H = 0;                                   //零点细调
    uint8_t    GS302_K0L = 0;                                   //零点细调
    uint8_t    GS302_KxH = 0;                                   //ADC增幅细调
    uint8_t    GS302_KxL = 0;                                   //ADC增幅细调

    float   CalibError=1;
    //*****************************烧写
    uint8_t    WReg_GainDACL;                                   //根据BANK区域选择，决定地址是多少：0x60\0x70\0x85
    uint8_t    WReg_GainDACH;                                   //根据BANK区域选择，决定地址是多少：0x61\0x71\0x86
    uint8_t    WReg_ZeroDACL;                                   //根据BANK区域选择，决定地址是多少：0x62\0x72\0x87
    uint8_t    WReg_ZeroDACH;                                   //根据BANK区域选择，决定地址是多少：0x63\0x73\0x88
    uint8_t    WReg_TADC;                                       //根据BANK区域选择，决定地址是多少：0x64\0x74\0x89

    uint8_t    W_GainDACL;                                      //灵敏度增益高位烧写数据
    uint8_t    W_GainDACH;                                      //灵敏度增益低位烧写数据
    uint8_t    W_ZeroDACL;                                      //零点细调低位烧写数据
    uint8_t    W_ZeroDACH;                                      //零点细调高位烧写数据
    uint8_t    W_TADC;

};

#endif // HALLDEVICE_H
